﻿
// -------------------------------------------------------------------------
//    @FileName         :    NFPacketSendUtil.cpp
//    @Author           :    gaoyi
//    @Date             :    24-8-8
//    @Email            :    445267987@qq.com
//    @Module           :    NFPacketSendUtil
//
// -------------------------------------------------------------------------

#include "NFPacketSendUtil.h"

#include "proto_access2zone.nanopb.h"
#include "NFComm/NFPluginModule/NFRoute.h"

#if NF_PLATFORM == NF_PLATFORM_WIN
#else
#include <netinet/in.h>
#endif
#include <NFLogicCommon/CustomPacketParse.h>
#include <NFLogicCommon/NFScopedMessageHead.h>
#include <NFLogicCommon/NFWatchTime.h>
#include <NFServerComm/NFServerCommon/NFIServerMessageModule.h>

#include "NFSession.h"
#include "NFPlayer.h"

int NFPacketSendUtil::SendToClient(NFSession* pSession, uint32_t cmd, const google::protobuf::Message* pstMsgRes)
{
    CHECK_EXPR(pSession, -1, "");
    CHECK_EXPR(pstMsgRes, -1, "");
    CHECK_EXPR(pstMsgRes->IsInitialized(), -2, "{}", pstMsgRes->InitializationErrorString());

    LOGSVR_TRACE("ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " MsgType:" << cmd);

    SendToClientDirectly(pSession, cmd, pstMsgRes);

    return 0;
}

int NFPacketSendUtil::SendToClient(NFSession* pSession, uint32_t cmd, const std::string& strData)
{
    CHECK_EXPR(pSession, -1, "");

    LOGSVR_TRACE("ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " MsgType:" << cmd);

    int iRetCode = 0;

    if (pSession->GetConnIndex() < 0)
    {
        iRetCode = pSession->GetConnIndex();
        LOGSVR_ERROR("Invalid ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " MsgType:" << cmd << " ResRetCode:" << iRetCode);
        return iRetCode;
    }

#ifdef NF_DEBUG_MODE
    NFWatchTime oWatchTime(cmd, 0, strData.size(), ENST_NET_OUT, &iRetCode);
#endif

    NFrame::Proto_FramePkg pkg;
    pkg.set_msg_id(cmd);
    pkg.set_module_id(NF_MODULE_CLIENT);
    pkg.set_msg_data(strData);
    int curSeq = pSession->IncreaseServerSeq();
    pkg.mutable_disp_info()->set_seq(curSeq);
    pkg.mutable_disp_info()->set_req_seq(NFScopedMessageHead::GetStackRequestSeq(pSession->GetGlobalId(), cmd));

    std::string pkgData = pkg.SerializePartialAsString();
    FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_LOGIC_SERVER, pSession->GetConnBusId(), E_ACCESS2ZONE_TRANSFER, pkgData.data(), pkgData.size(), pSession->GetConnIndex(), pSession->GetGlobalId());

    NFPlayer* pPlayer = pSession->GetPlayer();
    if (pPlayer)
    {
        LOGSVR_DEBUG_IF(cmd != proto_ff::E_CS_HEARTBEAT_RSP, "Send ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " Msg:" << cmd << " " << proto_ff::Proto_CS_CMD_Name(static_cast<proto_ff::Proto_CS_CMD>(cmd)) << " ResRetCode:" << iRetCode);
        pPlayer->CacheMsgRes(cmd, pSession->GetServerSeq(), pkgData.data(), pkgData.length());
    }

    return 0;
}

int NFPacketSendUtil::SendToClient(NFPlayer* pPlayer, uint32_t cmd, const google::protobuf::Message* pstMsgRes)
{
    CHECK_NULL(0, pPlayer);

    NFSession* pSession = pPlayer->GetClientSessionFast();
    CHECK_PLAYER_EXPR(pPlayer->GetRoleID(), pSession, -1, "");

    return SendToClient(pSession, cmd, pstMsgRes);
}

int NFPacketSendUtil::SendToClientDirectly(NFSession* pSession, uint32_t cmd, const google::protobuf::Message* pstMsgRes)
{
    CHECK_EXPR(pSession, -1, "");
    CHECK_EXPR(pstMsgRes, -1, "");
    CHECK_EXPR(pstMsgRes->IsInitialized(), -2, "{}", pstMsgRes->InitializationErrorString());

    LOGSVR_TRACE("ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " MsgType:" << cmd);

    int iRetCode = 0;

    if (pSession->GetConnIndex() < 0)
    {
        iRetCode = pSession->GetConnIndex();
        LOGSVR_ERROR("Invalid ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " MsgType:" << cmd << " ResRetCode:" << iRetCode);
        return iRetCode;
    }

    if (pSession->GetSessionState() == SESSION_STATE_TRANSFER)
    {
        return pSession->TransferCSMsgRes(cmd, pstMsgRes);
    }

    /*if (pstMsgRes->GetCachedSize() != pstMsgRes->ByteSize())
    {
        LOGSVR_ERROR("pstMsgRes->GetCachedSize()= " << pstMsgRes->GetCachedSize() << " not equal pstMsgRes->ByteSize()=" << pstMsgRes->ByteSize());
    }*/

#ifdef NF_DEBUG_MODE
    NFWatchTime oWatchTime(cmd, 0, pstMsgRes->GetCachedSize(), ENST_NET_OUT, &iRetCode);
#endif

    NFrame::Proto_FramePkg pkg;
    pkg.set_msg_id(cmd);
    pkg.set_module_id(NF_MODULE_CLIENT);
    pkg.set_msg_data(pstMsgRes->SerializePartialAsString());
    int curSeq = pSession->IncreaseServerSeq();
    pkg.mutable_disp_info()->set_seq(curSeq);
    pkg.mutable_disp_info()->set_req_seq(NFScopedMessageHead::GetStackRequestSeq(pSession->GetGlobalId(), cmd));

    std::string pkgData = pkg.SerializePartialAsString();
    FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_LOGIC_SERVER, pSession->GetConnBusId(), E_ACCESS2ZONE_TRANSFER, pkgData.data(), pkgData.size(), pSession->GetConnIndex(), pSession->GetGlobalId());

    NFPlayer* pPlayer = pSession->GetPlayer();
    if (pPlayer)
    {
        LOGSVR_TRACE_IF(cmd != proto_ff::E_CS_HEARTBEAT_RSP, "Send ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " Msg:" << cmd << " " << proto_ff::Proto_CS_CMD_Name(static_cast<proto_ff::Proto_CS_CMD>(cmd)) << " ResRetCode:" << iRetCode);
        pPlayer->CacheMsgRes(cmd, pSession->GetServerSeq(), pkgData.data(), pkgData.length());
    }

    LOGSVR_TRACE_IF(cmd != proto_ff::E_CS_HEARTBEAT_RSP, pstMsgRes->GetTypeName() << "[seq:" << curSeq << " cmd:" << cmd << " " << proto_ff::Proto_CS_CMD_Name(static_cast<proto_ff::Proto_CS_CMD>(cmd)) << " len:" << pkg.msg_data().size() << "]\n");

    LOGSVR_TRACE_IF(cmd != proto_ff::E_CS_HEARTBEAT_RSP, pkg.DebugString() << "\n" << pstMsgRes->DebugString());

    return 0;
}

int NFPacketSendUtil::SendToClientDirectly(int connID, int objID, int connBusID, uint32_t cmd, const google::protobuf::Message* pstMsgRes)
{
    CHECK_EXPR(pstMsgRes, -1, "");
    CHECK_EXPR(pstMsgRes->IsInitialized(), -2, "{}", pstMsgRes->InitializationErrorString());
    LOGSVR_DEBUG("ConnIndex:" << connID << " ObjID:" << objID << " connBusID:" << connBusID << " MsgType:" << cmd);

    int iRetCode = 0;
    if (connID < 0)
    {
        LOGSVR_ERROR("Invalid ConnIndex:" << connID << " ObjID:" << objID << " MsgType:" << cmd << " connBusID:" << connBusID);
        return iRetCode;
    }

    if (pstMsgRes->GetCachedSize() != pstMsgRes->ByteSize())
    {
        LOGSVR_ERROR("pstMsgRes->GetCachedSize()= " << pstMsgRes->GetCachedSize() << " not equal pstMsgRes->ByteSize()=" << pstMsgRes->ByteSize());
    }

#ifdef NF_DEBUG_MODE
    NFWatchTime oWatchTime(cmd, 0, pstMsgRes->GetCachedSize(), ENST_NET_OUT, &iRetCode);
#endif

    NFrame::Proto_FramePkg pkg;
    pkg.set_msg_id(cmd);
    pkg.set_module_id(NF_MODULE_CLIENT);
    pkg.set_msg_data(pstMsgRes->SerializePartialAsString());
    FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_LOGIC_SERVER, connBusID, E_ACCESS2ZONE_TRANSFER, pkg, connID, objID);

    LOGSVR_DEBUG_IF(cmd != proto_ff::E_CS_HEARTBEAT_RSP, pstMsgRes->GetTypeName() << "[cmd:" << cmd << " len:" << pkg.msg_data().size() << "]\n" << pkg.DebugString() << "\n" << pstMsgRes->DebugString());
    return 0;
}

int NFPacketSendUtil::SendToClientFinally(NFSession* pSession, void* pBuff, uint32_t ulSize)
{
    CHECK_NULL(0, pSession);
    CHECK_NULL(0, pBuff);

    LOGSVR_DEBUG("ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << ", size=" << ulSize);

    int iRetCode = 0;
    if (pSession->GetConnIndex() < 0)
    {
        iRetCode = pSession->GetConnIndex();
        LOGSVR_ERROR("Invalid ConnIndex:" << pSession->GetConnIndex() << " ObjID:" << pSession->GetGlobalId() << " ResRetCode:" << iRetCode);
        return iRetCode;
    }

    FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_LOGIC_SERVER, pSession->GetConnBusId(), E_ACCESS2ZONE_TRANSFER, (const char*)pBuff, ulSize, pSession->GetConnIndex(), pSession->GetGlobalId());
    return 0;
}

int NFPacketSendUtil::Broadcast(uint32_t cmd, const google::protobuf::Message* pstMsgRes)
{
    CHECK_NULL(0, pstMsgRes);
    NFrame::Proto_FramePkg pkg;
    pkg.set_msg_id(cmd);
    pkg.set_module_id(NF_MODULE_CLIENT);
    pkg.set_msg_data(pstMsgRes->SerializePartialAsString());

    std::string pkgData = pkg.SerializePartialAsString();

    std::vector<NF_SHARE_PTR<NFServerData>> vecServer = FindModule<NFIMessageModule>()->GetAllServer(NF_ST_LOGIC_SERVER, NF_ST_PROXY_SERVER);
    for (int i = 0; i < (int)vecServer.size(); i++)
    {
        auto pServerData = vecServer[i];
        if (pServerData)
        {
            FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_LOGIC_SERVER, pServerData->GetBusId(), E_ACCESS2ZONE_BROADCAST, pkgData.data(), pkgData.size(), 0, 0);
        }
    }
    return 0;
}

int NFPacketSendUtil::BroadcastAllLogic(uint32_t cmd, const google::protobuf::Message* pstMsgRes)
{
    CHECK_NULL(0, pstMsgRes);
    FindModule<NFIServerMessageModule>()->SendMsgToLogicServer(NF_ST_LOGIC_SERVER, LOCAL_ALL_ROUTE, cmd, *pstMsgRes);
    return 0;
}

int NFPacketSendUtil::Multicast(const std::vector<NFSession*>& vecSession, uint32_t cmd, const google::protobuf::Message* pstMsgRes)
{
    CHECK_NULL(0, pstMsgRes);
    NFrame::Proto_FramePkg pkg;
    pkg.set_msg_id(cmd);
    pkg.set_module_id(NF_MODULE_CLIENT);
    pkg.set_msg_data(pstMsgRes->SerializePartialAsString());

    std::string pkgData = pkg.SerializePartialAsString();

    std::set<int> setBusId;
    for (int i = 0; i < (int)vecSession.size(); i++)
    {
        auto pSession = vecSession[i];
        if (pSession)
        {
            pkg.mutable_redirect_info()->add_id(pSession->GetConnIndex());
            setBusId.insert(pSession->GetConnBusId());
        }
    }

    for (auto iter = setBusId.begin(); iter != setBusId.end(); ++iter)
    {
        FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_LOGIC_SERVER, *iter, E_ACCESS2ZONE_MULTICAST, pkgData.data(), pkgData.size(), 0, 0);
    }
    return 0;
}

int NFPacketSendUtil::SendErrToClient(NFSession* pSession, uint32_t req_cmd, int result)
{
    proto_ff::Proto_CSRsp message;
    proto_ff::Proto_CSErrorRsp* pErrorRsp = message.mutable_error();
    pErrorRsp->set_req_msg_id(req_cmd);
    pErrorRsp->set_error(result);

    return SendToClient(pSession, proto_ff::E_CS_ERROR, &message);
}

int NFPacketSendUtil::SendErrToClient(NFPlayer* pPlayer, uint32_t req_cmd, int result)
{
    CHECK_NULL(0, pPlayer);

    NFSession* pSession = pPlayer->GetClientSessionFast();
    CHECK_PLAYER_EXPR(pPlayer->GetRoleID(), pSession, -1, "");

    return SendErrToClient(pSession, req_cmd, result);
}

int NFPacketSendUtil::SendErrToClient(int connID, int objID, int connBusID, uint32_t req_cmd, proto_ff::Proto_CS_ErrorCode result)
{
    proto_ff::Proto_CSRsp message;
    proto_ff::Proto_CSErrorRsp* pErrorRsp = message.mutable_error();
    pErrorRsp->set_req_msg_id(req_cmd);
    pErrorRsp->set_error(result);

    return SendToClientDirectly(connID, objID, connBusID, proto_ff::E_CS_ERROR, &message);
}

int NFPacketSendUtil::SendGMResToClient(NFSession* pSession, int iRet, const std::string& content)
{
    CHECK_NULL(0, pSession);

    proto_ff::Proto_CSRsp rsp;
    proto_ff::Proto_CSGmRsp* pGM = rsp.mutable_gm();

    pGM->set_ret(iRet);
    pGM->set_content(content);
    return SendToClient(pSession, proto_ff::E_CS_GM_RSP, &rsp);
}


